package com.atguigu.gulimail.ware.service.impl;

import com.atguigu.common.constant.WareConstant;
import com.atguigu.common.exception.BizCodeEnum;
import com.atguigu.common.exception.BizException;
import com.atguigu.gulimail.ware.entity.PurchaseDetailEntity;
import com.atguigu.gulimail.ware.service.PurchaseDetailService;
import com.atguigu.gulimail.ware.service.WareSkuService;
import com.atguigu.gulimail.ware.vo.MergeVo;
import com.atguigu.gulimail.ware.vo.PurchaseDetailItemVo;
import com.atguigu.gulimail.ware.vo.PurchaseFinishVo;
import com.atguigu.gulimail.ware.vo.ReceivedVo;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;

import com.atguigu.gulimail.ware.dao.PurchaseDao;
import com.atguigu.gulimail.ware.entity.PurchaseEntity;
import com.atguigu.gulimail.ware.service.PurchaseService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;


@Service("purchaseService")
public class PurchaseServiceImpl extends ServiceImpl<PurchaseDao, PurchaseEntity> implements PurchaseService {

    @Resource
    PurchaseDetailService purchaseDetailService;

    @Resource
    WareSkuService wareSkuService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<PurchaseEntity> page = this.page(
                new Query<PurchaseEntity>().getPage(params),
                new QueryWrapper<PurchaseEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public PageUtils queryPageUnreceiveList(Map<String, Object> params) {
        IPage<PurchaseEntity> page = this.page(
                new Query<PurchaseEntity>().getPage(params),
                new QueryWrapper<PurchaseEntity>().eq("status", 0).or().eq("status", 1)
        );
        return new PageUtils(page);
    }

    /**
     * 合并采购需求到采购单上，可以人工合并也可以定时合并
     * 定时合并可以在 -- 库存预警的时候创建采购需求！
     *
     * @param mergeVo
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void mergePurchaseDetail(MergeVo mergeVo) {
        Long purchaseId = mergeVo.getPurchaseId();
        if (purchaseId == null) {
            // 合并到一张新的采购单中,创建一个新的采购单！
            PurchaseEntity purchaseEntity = new PurchaseEntity();
            purchaseEntity.setStatus(WareConstant.PurchaseEnum.CREATED.getCode());
            purchaseEntity.setCreateTime(new Date());
            purchaseEntity.setUpdateTime(new Date());
            this.save(purchaseEntity);
            purchaseId = purchaseEntity.getId();
        }
        // 确认采购单的状态是0或1 才可以进行合并
        PurchaseEntity byId = this.getById(purchaseId);
        if (!Arrays.asList(WareConstant.PurchaseEnum.CREATED.getCode(),
                WareConstant.PurchaseEnum.ASSIGNED.getCode()).contains(byId.getStatus())) {
            throw new BizException(BizCodeEnum.VALID_EXCEPTION);
        }
        // 合并到指定的采购单中,就用VO中的purchaseId即可。
        Long finalPurchaseId = purchaseId;
        // 拿到需要进行合并的 采购需求ID的集合
        List<Long> items = mergeVo.getItems();
        if (CollectionUtils.isEmpty(items)) {
            throw new BizException(BizCodeEnum.VALID_EXCEPTION);
        }
        // 判断采购需求项的仓库是同一仓库才能合并
        List<PurchaseDetailEntity> detailEntityList = purchaseDetailService.listByIds(items);
        if (CollectionUtils.isNotEmpty(detailEntityList)){
            Long wareId1 = detailEntityList.get(0).getWareId();
            for (int i = 1; i < detailEntityList.size(); i++) {
                if (!Objects.equals(wareId1, detailEntityList.get(i).getWareId())) {
                    throw new BizException(BizCodeEnum.VALID_EXCEPTION);
                }
            }
        }
        List<PurchaseDetailEntity> detailEntities = items.stream().map(i -> {
            PurchaseDetailEntity detailEntity = new PurchaseDetailEntity();
            detailEntity.setId(i);
            detailEntity.setPurchaseId(finalPurchaseId);
            detailEntity.setStatus(WareConstant.PurchaseDetailEnum.ASSIGNED.getCode());
            return detailEntity;
        }).collect(Collectors.toList());
        purchaseDetailService.updateBatchById(detailEntities);

        // 最后可以更新一下采购单的修改时间，因为这个采购单关联了n个采购需求数据！
        PurchaseEntity purchase = new PurchaseEntity();
        purchase.setId(purchaseId);
        purchase.setUpdateTime(new Date());
        this.updateById(purchase);
    }

    /**
     * 采购人员领取采购单功能。
     *
     * @param receivedVo 采购单的id集合
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void received(ReceivedVo receivedVo) {
        List<Long> ids = receivedVo.getIds();
        Long landerId = receivedVo.getLanderId();
        // 1、确认当前采购单是新建或者已分配状态
        // 1.1 采购人员应该只能领取属于自己的采购单
        List<PurchaseEntity> purchaseEntities = ids.stream().map(id -> {
            PurchaseEntity purchaseEntity = this.getById(id);
            if (!Objects.equals(purchaseEntity.getAssigneeId(), landerId)
                    || !Arrays.asList(WareConstant.PurchaseEnum.CREATED.getCode(), WareConstant.PurchaseEnum.ASSIGNED.getCode()).contains(purchaseEntity.getStatus())) {
                throw new BizException(BizCodeEnum.LANDER_EXCEPTION);
            }
            return purchaseEntity;
        }).peek(item -> {
            item.setStatus(WareConstant.PurchaseEnum.RECEIVE.getCode());
            item.setUpdateTime(new Date());
        }).collect(Collectors.toList());
        // 2、改变采购单的状态 -- 已领取
        this.updateBatchById(purchaseEntities);
        // 3、改变采购项的状态 -- 正在采购
        purchaseEntities.forEach(item -> {
            List<PurchaseDetailEntity> entities = purchaseDetailService.listDetailByPurchaseId(item.getId());
            if (CollectionUtils.isNotEmpty(entities)) {
                List<PurchaseDetailEntity> detailEntities = entities.stream().peek(entity -> {
                    entity.setStatus(WareConstant.PurchaseDetailEnum.BUYING.getCode());
                }).collect(Collectors.toList());
                purchaseDetailService.updateBatchById(detailEntities);
            }
        });
    }

    /**
     * 采购人员完成采购单
     *
     * @param doneVo
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void finishDone(PurchaseFinishVo doneVo) {
        Long purchaseId = doneVo.getId();
        // 1、确认当前采购单是已领取状态，并且采购人员应该只能完成属于自己的采购单
        PurchaseEntity byId = this.getById(purchaseId);
        if (!Objects.equals(doneVo.getLanderId(), byId.getAssigneeId()) || byId.getStatus() != WareConstant.PurchaseEnum.RECEIVE.getCode()) {
            throw new BizException(BizCodeEnum.VALID_EXCEPTION);
        }
        // 2、改变采购项的状态 -- 已完成/有异常
        boolean flag = true;  // 判断采购项有异常的标志位
        List<PurchaseDetailItemVo> items = doneVo.getItems();
        if (CollectionUtils.isEmpty(items)) {
            throw new BizException(BizCodeEnum.VALID_EXCEPTION);
        }
        List<PurchaseDetailEntity> updates = new ArrayList<>();
        Long wareId = null;
        BigDecimal purchaseAmount = new BigDecimal("0");
        for (PurchaseDetailItemVo item : items) {
            PurchaseDetailEntity detailEntity = new PurchaseDetailEntity();
            if (item.getStatus() == WareConstant.PurchaseDetailEnum.HASERROR.getCode()) {
                flag = false;
            } else {
                // 4、将成功采购的入库，并填写采购项单价 -- 对应第4步
                PurchaseDetailEntity entity = purchaseDetailService.getById(item.getItemId());
                wareId = entity.getWareId();
                entity.setSkuPrice(item.getSkuPrice());
                purchaseDetailService.updateById(entity);
                // 计算采购单总金额
                BigDecimal detailPrice = entity.getSkuPrice().multiply(new BigDecimal(entity.getSkuNum()));
                purchaseAmount = purchaseAmount.add(detailPrice);
                wareSkuService.addStock(entity.getSkuId(), entity.getWareId(), entity.getSkuNum());
            }
            detailEntity.setStatus(item.getStatus());
            detailEntity.setId(item.getItemId());
            updates.add(detailEntity);
        }
        purchaseDetailService.updateBatchById(updates);
        // 3、改变采购单的状态 -- 已完成/有异常 有一个采购项失败就应该是有异常
        PurchaseEntity purchaseEntity = new PurchaseEntity();
        purchaseEntity.setId(purchaseId);
        purchaseEntity.setStatus(flag ? WareConstant.PurchaseEnum.FINISH.getCode() : WareConstant.PurchaseEnum.HASERROR.getCode());
        purchaseEntity.setUpdateTime(new Date());
        // 5、并在采购单更改仓库id和总金额
        purchaseEntity.setWareId(wareId);
        purchaseEntity.setAmount(purchaseAmount);
        this.updateById(purchaseEntity);
        // 4、把成功的采购项对应采购的商品sku_id，增加sku相应的库存，并填写采购项的采购金额。 -- 入库
    }

}